package com.douqu.game.main.server;

import com.alibaba.fastjson.JSONObject;
import com.bean.core.util.TimeUtils;
import com.douqu.game.core.config.StableDataConfig;
import com.douqu.game.core.config.sprite.MasterConfig;
import com.douqu.game.core.controller.PlayerController;
import com.douqu.game.core.database.model.PlayerModel;
import com.douqu.game.core.e.E_ActivityCampStatus;
import com.douqu.game.core.e.E_Attribute;
import com.douqu.game.core.e.E_AuctionSource;
import com.douqu.game.core.e.E_StableDataType;
import com.douqu.game.core.entity.Player;
import com.douqu.game.core.entity.activity.MatchBaseInfo;
import com.douqu.game.core.entity.activity.RankCamp;
import com.douqu.game.core.entity.activity.RankPlayer;
import com.douqu.game.core.entity.battle.BattleResultParamCampSingle;
import com.douqu.game.core.entity.battle.BattleTemp;
import com.douqu.game.core.entity.battle.SpriteTemp;
import com.douqu.game.core.entity.db.CardDB;
import com.douqu.game.core.entity.ext.BagInfo;
import com.douqu.game.core.entity.ext.ChallengeInfo;
import com.douqu.game.core.entity.ext.MailInfo;
import com.douqu.game.core.entity.ext.data.challenge.CampBattleData;
import com.douqu.game.core.factory.*;
import com.douqu.game.core.protobuf.SGCommonProto;
import com.douqu.game.core.util.LogUtils;
import com.douqu.game.main.GameServer;
import com.douqu.game.main.database.mapper.read.ReadPlayerMapper;
import com.douqu.game.main.service.PlayerService;
import io.netty.util.internal.StringUtil;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @Author: Bean
 * @Description:
 * @Date: 2018-03-16 16:49
 */
public class ActivityCampManager {

    private String index = "";

    private E_ActivityCampStatus status;
    /** 开始时间(19:00:00) */
    private String startTime = "19:00:00";
    /** 持续时间 */
    private int totalTime = 90 * 60 * 1000;
    /** 间隔时间 */
    private int intervalTime = 2 * 60 * 1000;

    private String httpPort;

    /** 当前阵营排行 */
    private List<RankCamp> rankCampList = new CopyOnWriteArrayList<>();
    /** 当前玩家排行 */
    private List<RankPlayer> rankPlayerList = new CopyOnWriteArrayList<>();
    /** 最高击杀玩家 */
    private RankPlayer maxWinCountPlayer;
    /** 最高连胜玩家 */
    private RankPlayer maxContinueWinPlayer;
    /** 最高功勋玩家 */
    private RankPlayer maxExploitPlayer;

    /**
     * 所有参加阵营战的玩家
     * 直到下一次活动才清除这个list
     */
    private List<MatchBaseInfo> playerList = new CopyOnWriteArrayList<>();
    /**
     * 当前在活动的的玩家，复活次数用完后就从map里删除
     */
    private Map<String, MatchBaseInfo> playerMap = new ConcurrentHashMap<>();

    private static ActivityCampManager instance = null;

    private ActivityCampManager()
    {
        this.maxWinCountPlayer = new RankPlayer();
        this.maxExploitPlayer = new RankPlayer();
        this.maxContinueWinPlayer = new RankPlayer();
    }

    public static ActivityCampManager getInstance()
    {
        if(instance == null)
            instance = new ActivityCampManager();

        return instance;
    }

//    public void init(String index, String status, String httpPort, RankPlayer maxWinCountPlayer, RankPlayer maxContinueWinPlayer, RankPlayer maxExploitPlayer,
//                     List<RankPlayer> rankPlayerList, List<RankCamp> rankCampList, List<String> playerIndexList)
    public boolean init(JSONObject jsonObject)
    {
        this.index = jsonObject.getString(ConstantFactory.ACTIVITY_INDEX);
        this.httpPort = jsonObject.getString(ConstantFactory.ACTIVITY_SERVER_HTTP);
        this.status = E_ActivityCampStatus.valueOf(jsonObject.getString(ConstantFactory.ACTIVITY_STATUS));
        this.maxWinCountPlayer = JSONObject.parseObject(jsonObject.getString(ConstantFactory.MAX_WIN_COUNT_PLAYER), RankPlayer.class);
        this.maxContinueWinPlayer = JSONObject.parseObject(jsonObject.getString(ConstantFactory.MAX_CONTINUE_WIN_PLAYER), RankPlayer.class);
        this.maxExploitPlayer = JSONObject.parseObject(jsonObject.getString(ConstantFactory.MAX_EXPLOIT_PLAYER), RankPlayer.class);
        this.rankPlayerList = JSONObject.parseArray(jsonObject.getString(ConstantFactory.RANK_PLAYER_LIST), RankPlayer.class);
        this.rankCampList = JSONObject.parseArray(jsonObject.getString(ConstantFactory.RANK_CAMP_LIST), RankCamp.class);

        boolean flag = false;
        if (status != E_ActivityCampStatus.RUN_ING){
            LogUtils.info("重新连接活动服 -> :" + "开始发放邮件奖励");
            if (!GameServer.getInstance().getWorldManager().rankRewardRest(rankPlayerList))
                flag = false;
            else{
                LogUtils.info("重新连接活动服 -> :" + "发放邮件奖励完成");
                flag = true;
            }
        }


        LogUtils.info("初始化的排行 -> maxWinCountPlayer:" + maxWinCountPlayer);
        LogUtils.info("初始化的排行 -> maxExploitPlayer:" + maxExploitPlayer);
        LogUtils.info("初始化的排行 -> maxContinueWinPlayer:" + maxContinueWinPlayer);


        PlayerController playerController = null;
        playerMap.clear();
        MatchBaseInfo baseInfo = null;
        List<String> offlineList = new ArrayList<>();
        List<String> playerIndexList =JSONObject.parseArray(jsonObject.getString(ConstantFactory.APPLY_PLAYER_LIST), String.class);
        for(String playerIndex : playerIndexList)
        {
            playerController = GameServer.getInstance().getWorldManager().getPlayerController(playerIndex);
            if(playerController != null)
            {
                baseInfo = new MatchBaseInfo(playerController.getPlayer(), GameServer.getInstance().getServerId());
                playerMap.put(playerIndex, baseInfo);
                playerList.add(baseInfo);
            }
            else
            {
                offlineList.add(playerIndex);
            }
        }

        if(offlineList.size() > 0)
        {
            ReadPlayerMapper readPlayerMapper = SpringContext.getBean(ReadPlayerMapper.class);
            List<PlayerModel> modelList = readPlayerMapper.getPlayerListByIndex(offlineList);
            for(PlayerModel playerModel : modelList)
            {
                baseInfo = new MatchBaseInfo(new Player(playerModel), GameServer.getInstance().getServerId());
                playerMap.put(playerModel.getObjectIndex(), baseInfo);
                playerList.add(baseInfo);
            }
        }

        return flag;
    }

    public void initTime(JSONObject jsonObject)
    {
        this.startTime = jsonObject.getString(CodeFactory.KEY_START_TIME);
        this.totalTime = jsonObject.getInteger(CodeFactory.KEY_TOTAL_TIME);
        this.intervalTime = jsonObject.getInteger(CodeFactory.KEY_INTERVAL_TIME);

        LogUtils.warn("更新活动开始时间 -> " + startTime);
        LogUtils.warn("更新活动持续时间 -> " + totalTime);
        LogUtils.warn("更新匹配间隔时间 -> " + intervalTime);
    }


//    public void checkEnd()
//    {
//        if(endTime > 0 && DataFactory.currentTime >= endTime)
//        {
//            end(index);
//        }
//    }


    public void update(JSONObject jsonObject)
    {
        if(jsonObject.containsKey(ConstantFactory.MAX_WIN_COUNT_PLAYER))
        {
            this.maxWinCountPlayer = JSONObject.parseObject(jsonObject.getString(ConstantFactory.MAX_WIN_COUNT_PLAYER), RankPlayer.class);
        }

        if(jsonObject.containsKey(ConstantFactory.MAX_EXPLOIT_PLAYER))
        {
            this.maxExploitPlayer = JSONObject.parseObject(jsonObject.getString(ConstantFactory.MAX_EXPLOIT_PLAYER), RankPlayer.class);
        }

        if(jsonObject.containsKey(ConstantFactory.MAX_CONTINUE_WIN_PLAYER))
        {
            this.maxContinueWinPlayer = JSONObject.parseObject(jsonObject.getString(ConstantFactory.MAX_CONTINUE_WIN_PLAYER), RankPlayer.class);
        }

        if(jsonObject.containsKey(ConstantFactory.RANK_PLAYER_LIST))
        {
            this.rankPlayerList = JSONObject.parseArray(jsonObject.getString(ConstantFactory.RANK_PLAYER_LIST), RankPlayer.class);
        }

        if(jsonObject.containsKey(ConstantFactory.RANK_CAMP_LIST))
        {
            this.rankCampList = JSONObject.parseArray(jsonObject.getString(ConstantFactory.RANK_CAMP_LIST), RankCamp.class);
        }
    }



    public void applySuccess(PlayerController playerController)
    {
        MatchBaseInfo player = playerMap.get(playerController.getObjectIndex());
        if(player != null)
        {
            player.update(playerController.getPlayer());
        }
        else
        {
            player = new MatchBaseInfo(playerController.getPlayer(), GameServer.getInstance().getServerId());
            playerMap.put(player.getObjectIndex(), player);
        }

        playerList.remove(player);//删除旧的
        playerList.add(player);//添加新的
    }

    public void removePlayer(String playerIndex)
    {
        playerMap.remove(playerIndex);
    }


    /**
     * 玩家结算
     * @param player
     * @param target
     * @param masterHPRate
     * @param armyHPRate
     * @return
     */
    public BattleResultParamCampSingle campBattleResult(boolean win, Player player, MatchBaseInfo target, int masterHPRate, int armyHPRate)
    {
        CampBattleData campBattleData = player.getCampBattleData();
        BattleResultParamCampSingle resultParam = null;
        if(win)
        {
            BagInfo bagInfo = player.getExtInfo(BagInfo.class);

            StableDataConfig stableData = DataFactory.getInstance().getGameObject(DataFactory.STABLE_DATA_KEY, E_StableDataType.CAMP_ACTIVITY_REWARD.getCode());
            int exploit = stableData.getCampActivityRewardExploit();
            bagInfo.addAsset(ConfigFactory.ASSET_EXPLOIT_KEY, exploit);
            campBattleData.win(target, exploit, masterHPRate, armyHPRate);

            resultParam = new BattleResultParamCampSingle(new MatchBaseInfo(player, GameServer.getInstance().getServerId()));
            resultParam.setAddExploit(exploit);
            resultParam.setCurTotalExploit(campBattleData.curTotalExploit);
            resultParam.setCurMaxContinueWin(campBattleData.curMaxContinueWin);
            resultParam.setCurWinCount(campBattleData.curWinCount);
        }
        else
        {
            int beforeReviveCount = campBattleData.reviveCount;
            if(campBattleData.revive(target))
            {
                //复活成功,通知活动服务器,重新加入匹配列表中
                resultParam = new BattleResultParamCampSingle(new MatchBaseInfo(player, GameServer.getInstance().getServerId()));
                resultParam.setBeforeReviveCount(beforeReviveCount);
                resultParam.setAfterReviveCount(campBattleData.reviveCount);
            }
            else
            {
                removePlayer(player.getObjectIndex());

                //没有复活次数,通知活动服务器,从活动中删除
                resultParam = new BattleResultParamCampSingle(null);
                resultParam.setAfterReviveCount(beforeReviveCount);
                resultParam.setBeforeReviveCount(beforeReviveCount);
            }
        }

        return resultParam;
    }

    public void start(JSONObject jsonObject)
    {
//        endTime = CampActivityFactory.getCampActivityEndTime(CampActivityFactory.getCampActivityStartTime());

        if(jsonObject != null)
        {
            if(jsonObject.containsKey(ConstantFactory.RANK_CAMP_LIST))
            {
                this.rankCampList = JSONObject.parseArray(jsonObject.getString(ConstantFactory.RANK_CAMP_LIST), RankCamp.class);
                LogUtils.info("更新阵营排行 -> " + rankCampList);
            }
            if(jsonObject.containsKey(ConstantFactory.RANK_PLAYER_LIST))
            {
                this.rankPlayerList = JSONObject.parseArray(jsonObject.getString(ConstantFactory.RANK_PLAYER_LIST), RankPlayer.class);
            }
        }

        //活动时间中间开始的不检测
        if(!jsonObject.getBoolean(CodeFactory.KEY_RUNNING))
        {
            PlayerController playerController = null;
            List<String> offlineList = new ArrayList<>();
            for(MatchBaseInfo baseInfo : playerList)
            {
                playerController = GameServer.getInstance().getWorldManager().getPlayerController(baseInfo.getObjectIndex());
                if(playerController != null)
                {
                    //检测上一次活动奖励
                    playerController.getPlayer().getCampBattleData().checkReward(index, getCampRank(baseInfo.getCamp()));
                    playerController.getPlayer().getCampBattleData().clearReward();
                }
                else
                {
                    offlineList.add(baseInfo.getObjectIndex());
                }
            }

            PlayerService playerService = SpringContext.getBean(PlayerService.class);
            List<PlayerModel> modelList = playerService.getPlayerListByIndex(offlineList);
            Player player = null;
            List<Player> savePlayerList = new ArrayList<>();
            for(PlayerModel playerModel : modelList)
            {
                //处理离线玩家 上次奖励
                player = new Player(playerModel);
                player.getCampBattleData().checkReward(index, getCampRank(player.camp));
                player.getCampBattleData().clearReward();
                savePlayerList.add(player);
            }

            playerService.updatePlayers(savePlayerList, false, ChallengeInfo.class, MailInfo.class);
        }

    }


  
    public boolean end(JSONObject jsonObject)
    {
        setStatus(E_ActivityCampStatus.CLEAR_ING);

        if(jsonObject.containsKey(ConstantFactory.FIRST_CAMP_PLAYER_LIST))
        {
            StableDataConfig stableDataConfig = DataFactory.getInstance().getGameObject(DataFactory.STABLE_DATA_KEY, E_StableDataType.CAMP_ACTIVITY_AUCTION_REWARD.getCode());
            if (stableDataConfig == null){
                LogUtils.error("StableDataConfig error ->" + "no have type " + E_StableDataType.CAMP_ACTIVITY_AUCTION_REWARD.getMsg());
                return false;
            }

            List<String> firstCampPlayerList = JSONObject.parseArray(jsonObject.getString(ConstantFactory.FIRST_CAMP_PLAYER_LIST), String.class);
            //日志记录阵营战可以分红的玩家列表
            GameServer.getInstance().startThread(()->{
                LogUtils.info("campActivity auction bonus playerList:");
                StringBuffer stringBuffer = new StringBuffer();
                for (String object:firstCampPlayerList){
                    stringBuffer.append(object);
                    stringBuffer.append("\t");
                }
                LogUtils.info(stringBuffer.toString());
            });
            GameServer.getInstance().getWorldAuctionData().newAuction(stableDataConfig.getCampActivityAuctionReward(), firstCampPlayerList, E_AuctionSource.AUCTION_SOURCE_CAMP.getCode());
        }

        PlayerController playerController = null;
        for (MatchBaseInfo math:playerList){
            playerController = GameServer.getInstance().getWorldManager().getPlayerController(math.getObjectIndex());
            if (playerController != null)
                playerController.getPlayer().getCampBattleData().checkReward(index, getCampRank(math.getCamp()));
            //playerController.getPlayer().getCampBattleData().clearReward();
        }
        playerMap.clear();
        playerList.clear();
        WorldManager worldManager = GameServer.getInstance().getWorldManager();
        boolean flag = false;
        if (worldManager.rankRewardRest(rankPlayerList))
            flag = true;
        worldManager.clearPlayerBattleTemp(SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_SPAN_CAMP_VALUE);
        return flag;
    }

    public int getCampRank(int camp)
    {
        for(int i = 0; i < rankCampList.size(); i++)
        {
            if(rankCampList.get(i).getCamp() == camp)
                return i+1;
        }
        return 0;
    }

    public int getMyRank(String playerIndex)
    {
        int rank = rankPlayerList.indexOf(new RankPlayer(playerIndex));

        return rank == -1 ? 0 : (rank+1);
    }

    public BattleResultParamCampSingle directEndCampBattle(boolean win, Player player, MatchBaseInfo target, BattleTemp battleTemp)
    {
        BattleResultParamCampSingle resultParam = null;
        if(win)
        {
            if(battleTemp != null)
            {
                GameServer.getInstance().getWorldManager().addPlayerBattleTemp(SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_SPAN_CAMP_VALUE, player.getObjectIndex(), battleTemp);

                resultParam = campBattleResult(true, player, target, battleTemp.getMasterHPRate(), battleTemp.getArmyHPRate());
            }
            else
            {
                battleTemp = GameServer.getInstance().getWorldManager().getSpriteBattleTemp(SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_SPAN_CAMP_VALUE, player.getObjectIndex());
                if(battleTemp == null)
                {
                    battleTemp = new BattleTemp();
                    battleTemp.setBaseInfo(new MatchBaseInfo(player, GameServer.getInstance().getServerId()));
                    battleTemp.setIndexInfo(player.getObjectIndex());
                    MasterConfig masterConfig = DataFactory.getInstance().getGameObject(DataFactory.MASTER_KEY, player.master);
                    int hp = masterConfig.getAttribute(E_Attribute.HP.getCode(), player.getLv(), player.getMasterExtraAddAttributes(E_Attribute.HP.getCode()));
                    battleTemp.setMaster(new SpriteTemp(player.master, player.getLv(), hp, hp, hp, 0));
                    int index = 0;
                    for(CardDB cardDB : player.getCampCardList())
                    {
                        hp = cardDB.getAttribute(E_Attribute.HP.getCode());
                        battleTemp.addSoldierTemp(new SpriteTemp(cardDB.id, cardDB.getLv(), hp, hp, hp, index++), true);
                    }

                    GameServer.getInstance().getWorldManager().addPlayerBattleTemp(SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_SPAN_CAMP_VALUE, player.getObjectIndex(), battleTemp);
                }

                double rate = (double)target.getFc() / player.fc;
                //2080423 添加以下规则，变成平方
                rate = Math.pow(rate, 2);
                battleTemp.getMaster().addHPByRate(-rate);
                if(battleTemp.getMaster().getHp() > 0)
                {
                    for(SpriteTemp spriteTemp : battleTemp.getSoldierList())
                    {
                        spriteTemp.addHPByRate(-rate);
                    }

                    resultParam = campBattleResult(true, player, target, battleTemp.getMasterHPRate(), battleTemp.getArmyHPRate());
                }
                else
                {
                    GameServer.getInstance().getWorldManager().clearPlayerBattleTemp(SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_SPAN_CAMP_VALUE, player.getObjectIndex());

                    resultParam = campBattleResult(false, player, target, 0, 0);
                }
            }
        }
        else
        {
            GameServer.getInstance().getWorldManager().clearPlayerBattleTemp(SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_SPAN_CAMP_VALUE, player.getObjectIndex());

            resultParam = campBattleResult(false, player, target, 0, 0);
        }

        return resultParam;
    }


    public long getStartLongTime()
    {
        try {
            return TimeUtils.getTimeByString(TimeUtils.getCurrentTime(TimeUtils.YYYY_MM_DD) + " " + startTime);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;
    }


    public long getCampActivityIntervalNextStartTime()
    {
        try{
            long startLongTime = getStartLongTime();
            LogUtils.info("startLongTime->" + startLongTime);
            final long currentTime = DataFactory.currentTime;
            LogUtils.info("currentTime->" + currentTime);
            long endTime = totalTime + startLongTime;
            LogUtils.info("endTime->" + endTime);
            if(currentTime > endTime)
                startTime += 24 * 60 * 60 * 1000;

            LogUtils.info("startTime->" + startTime);
            if(currentTime <= startLongTime)
                return startLongTime - currentTime;

            long offset = (currentTime - startLongTime) % intervalTime;
            LogUtils.info("offset->" + offset);
            return offset == 0 ? 0 : intervalTime - offset;

        }catch (Exception e){
            e.printStackTrace();
        }

        return 0;
    }


    public MatchBaseInfo getPlayer(String playerIndex)
    {
        return playerMap.get(playerIndex);
    }


    public List<RankCamp> getRankCampList() {
        return rankCampList;
    }

    public void setRankCampList(List<RankCamp> rankCampList) {
        this.rankCampList = rankCampList;
    }


    public List<RankPlayer> getRankPlayerList() {
        return rankPlayerList;
    }

    public void setRankPlayerList(List<RankPlayer> rankPlayerList) {
        this.rankPlayerList = rankPlayerList;
    }


    public RankPlayer getMaxWinCountPlayer() {
        return maxWinCountPlayer;
    }

    public void setMaxWinCountPlayer(RankPlayer maxWinCountPlayer) {
        this.maxWinCountPlayer = maxWinCountPlayer;
    }

    public RankPlayer getMaxContinueWinPlayer() {
        return maxContinueWinPlayer;
    }

    public void setMaxContinueWinPlayer(RankPlayer maxContinueWinPlayer) {
        this.maxContinueWinPlayer = maxContinueWinPlayer;
    }

    public RankPlayer getMaxExploitPlayer() {
        return maxExploitPlayer;
    }

    public void setMaxExploitPlayer(RankPlayer maxExploitPlayer) {
        this.maxExploitPlayer = maxExploitPlayer;
    }

    public Map<String, MatchBaseInfo> getPlayerMap() {
        return playerMap;
    }

    public String getHttpPort() {
        return httpPort;
    }

    public E_ActivityCampStatus getStatus() {
        return status;
    }

    public String getIndex() {
        return index;
    }

    public void setIndex(String index) {
        this.index = index;
    }

    //    public void setIndex(String index)
//    {
//        if(!Utils.isNullOrEmpty(this.index) && !this.index.equals(index))
//        {
//            playerMap.remove(this.index);
//        }
//        this.index = index;
//    }

    public void setStatus(E_ActivityCampStatus status)
    {
        this.status = status;
    }

//    public long getEndTime() {
//        return endTime;
//    }
//
//    public void setEndTime(long endTime) {
//        this.endTime = endTime;
//    }


    public String getStartTime() {
        return startTime;
    }

    public void setStartTime(String startTime) {
        this.startTime = startTime;
    }

    public int getTotalTime() {
        return totalTime;
    }

    public void setTotalTime(int totalTime) {
        this.totalTime = totalTime;
    }

    public int getIntervalTime() {
        return intervalTime;
    }

    public void setIntervalTime(int intervalTime) {
        this.intervalTime = intervalTime;
    }


    public static void main(String[] args) {
        ActivityCampManager.getInstance().setStartTime("19:00:00");
        ActivityCampManager.getInstance().setTotalTime(5400000);
        ActivityCampManager.getInstance().setIntervalTime(120000);
        int countdown = (int) ((ActivityCampManager.getInstance().getCampActivityIntervalNextStartTime() + 9000) / 1000);
        LogUtils.info("count:" + countdown);
    }

}
